home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
ASM-O.ZIP
/
ONEKEY.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-02-05
|
10KB
|
203 lines
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
ORG 9H*4 ;The keyboard Interrupt
KEYBOARD_INT_VECTOR LABEL DWORD
ORG 1CH*4 ;Timer Interrupt
TIMER_VECTOR LABEL DWORD
VECTORS ENDS
ROM_BIOS_DATA SEGMENT AT 40H ;The ROM BIOS data area in low memory
ORG 1AH ;This is where the keyboard buffer is.
ROM_BUFFER_HEAD DW ? ;The position of the buffer's head
ROM_BUFFER_TAIL DW ? ;And tail.
KB_BUFFER DW 16 DUP (?) ;Reserve space for the buffer itself
KB_BUFFER_END LABEL WORD ;Buffer's end is stored here.
ROM_BIOS_DATA ENDS
CODE_SEG SEGMENT ;Begin the Code segment holding the programs
ASSUME CS:CODE_SEG
ORG 100H ;Com files start at ORG 100H
BEGIN: JMP INIT_VECTORS ;Skip over data area
COPY_RIGHT DB '(C) 1984 S. Holzner' ;The Author's signature
KEYS DW 30 DUP(0) ;The keys we replace
FINISHED_FLAG DB 1 ;If not finished, timer will stuff buffer
COMMANDS DW 1530 DUP(0) ;Scan and ASCII codes of commands
COMMAND_INDEX DW 1 ;Stores position in command (for timer)
ROM_KEYBOARD_INT DD 1 ;Called to interpret keyboard signals
ROM_TIMER DD 1 ;The Timer interrupt's address
INTERCEPT_KEYBOARD_INT PROC NEAR ;Here it is.
ASSUME DS:NOTHING ;Free DS
PUSH DS ;Save all used registers
PUSH SI
PUSH DI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSHF ;Pushf for Keyboard Int's IRET
CALL ROM_KEYBOARD_INT ;Have new key put into keyboard buffer
ASSUME DS:ROM_BIOS_DATA ;Set up to point at keyboard buffer.
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,ROM_BUFFER_TAIL ;Was there a character? If Tail equals
CMP BX,ROM_BUFFER_HEAD ; Head then no real character typed.
JNE NEWCHAR
JMP NO_NEW_CHARACTERS ;Jump out, no new characters.
NEWCHAR:SUB BX,2 ;Move back two bytes from tail;
CMP BX,OFFSET KB_BUFFER ;Do we have to wrap?
JAE NO_WRAP ;No
MOV BX,OFFSET KB_BUFFER_END ;Wrap by moving two bytes
SUB BX,2 ; before buffer end.
NO_WRAP:MOV AX,[BX] ;Get the character into AX
CMP FINISHED_FLAG,1 ;Done stuffing the buffer with last command?
JE FIN ;Yes, proceed
JMP NO_NEW_CHARACTERS ;No, leave.
FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish
LEA SI,KEYS ;Point source index at keys to replace
MOV CX,30 ;Loop over all of them
LOOPER: CMP AX,CS:[SI] ;Match to given key (in AX)?
JE FOUND ;Yes, key found, continue on.
ADD SI,2 ;Point to next key to check it.
LOOP LOOPER ;Go back for next one.
JMP NO_NEW_CHARACTERS ;Loop finished without match - leave.
FOUND: CLI ;Turn off hardware (timer, keyboard) Interrupts
LEA SI,COMMANDS ;Set up to read command
NEG CX ;Find the location of first word of command
ADD CX,30
MOV AX,CX
MOV CX,102
MUL CL
ADD SI,AX
MOV COMMAND_INDEX,SI ;And move it into Command_Index
STUFF: MOV AX,CS:[SI] ;Here we go - get ready to stuff word in buffer.
ADD SI,2 ;Point to the command's next character
CMP AX,0 ;Is it a zero? (End of command)
JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1
MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
JL NO_WRAP2 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Wrap
NO_WRAP2:
CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
JE BUFFER_FULL ;Time to leave, set Finished_Flag=0.
ADD COMMAND_INDEX,2 ;Move to next word in command
MOV [BX],AX ;Put it into the buffer right here.
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
JL NO_WRAP3 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP3:
MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
JMP STUFF ;Back to stuff in another character.
BUFFER_FULL: ;If buffer is full, let timer take over
MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0.
NO_NEW_CHARACTERS:
POP AX ;Restore everything before departure.
POP BX
POP CX
POP DX
POP DI
POP SI
POP DS
STI
IRET ;An interrupt deserves an IRET
INTERCEPT_KEYBOARD_INT ENDP
ASSUME DS:CODE_SEG
INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer
PUSHF ;Store used flags
PUSH DS ;Save DS since we'll change it
PUSH CS ;Put current value of CS into DS
POP DS
CALL ROM_TIMER ;Make obligatory call
PUSHF
CMP FINISHED_FLAG,1 ;Do we have to do anything?
JE OUT ;No, leave
CLI ;Yes, start by clearing interrupts
PUSH DS ;Save these.
PUSH SI
PUSH DX
PUSH BX
PUSH AX
ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again.
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,ROM_BUFFER_TAIL ;Prepare to put charaters in at tail
MOV FINISHED_FLAG,1 ;Assume we'll finish
MOV SI,COMMAND_INDEX ;Find where we left ourselves
STUFF2: MOV AX,CS:[SI] ;The same stuff loop as above.
ADD SI,2 ;Point to next command character.
CMP AX,0 ;Is it zero? (end of command)
JNE OVER ;No, continue.
JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1
OVER: MOV DX,BX ;Find position in buffer from BX
ADD DX,2 ;Move to next position for this word
CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
JL NO_WRAP4 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Do the Wrap rap.
NO_WRAP4:
CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
JE BUFFER_FULL2 ;Time to leave, come back later.
ADD COMMAND_INDEX,2 ;Point to next word of command.
MOV [BX],AX ;Put into buffer
ADD BX,2 ;Point to next space in buffer
CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
JL NO_WRAP5 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP5:
MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
JMP STUFF2 ;Back to stuff in another character
BUFFER_FULL2:
MOV FINISHED_FLAG,0 ;Set flag to not-done-yet.
NO_NEW_CHARACTERS2:
POP AX ;Restore these.
POP BX
POP DX
POP SI
POP DS
OUT: POPF ;And Exit.
POP DS
IRET ;With customary IRET
INTERCEPT_TIMER ENDP
INIT_VECTORS PROC NEAR ;Rest Interrupt vectors here
ASSUME DS:VECTORS
PUSH DS
MOV AX,VECTORS
MOV DS,AX
CLI ;Don't allow interrupts
MOV AX,KEYBOARD_INT_VECTOR ;Get and store old interrupt address
MOV ROM_KEYBOARD_INT,AX
MOV AX,KEYBOARD_INT_VECTOR[2]
MOV ROM_KEYBOARD_INT[2],AX
MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
MOV KEYBOARD_INT_VECTOR[2],CS ;And put ours in place.
MOV AX,TIMER_VECTOR ;Now same for timer
MOV ROM_TIMER,AX
MOV AX,TIMER_VECTOR[2]
MOV ROM_TIMER[2],AX
MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER
MOV TIMER_VECTOR[2],CS ;And intercept that too.
STI
ASSUME DS:ROM_BIOS_DATA
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,OFFSET KB_BUFFER ;Clear the keyboard buffer.
MOV ROM_BUFFER_HEAD,BX
MOV ROM_BUFFER_TAIL,BX
MOV DX,OFFSET INIT_VECTORS ;Prepare to attach in memory
INT 27H ;And do so.
INIT_VECTORS ENDP
CODE_SEG ENDS
END BEGIN ;End Begin so that we jump there first.